/**
 * 节流：降低函数触发的频率
 * @param func
 * @param wait
 */
export function throttle(func: Function, wait: number) {
    if (typeof func !== 'function') throw TypeError('func must be an function')
    if (typeof wait === 'undefined') wait = 500

    /*
      从第一个点开始延后[等待时间]执行，如果执行到第二个点，发现这个时间还没有超过等待时间，则让它延后[(等待时间) - (第一个点到第二个点的时间)]这么久执行
      如果执行到第三个点的时间，发现已经超过了等待的时间，则立即执行即可
      |._.__|__.___|_____|_____|__________...
     */
    let timer: number | undefined = undefined,
        previous = 0;
    return function proxy(this: any, ...params: any[]) {
        let self = this,
            now = Date.now(),
            // 计算传入的等待时间和(当前时间和上次执行时间的时间差)的时间差
            remaining: number = wait - (now - previous);
        // 如果时间差小于等于0，则说明超过了传入的等待时间，直接执行即可
        if (remaining <= 0) {
            clearTimeout(timer)
            // 重置previous|timer
            timer = undefined
            previous = now
            func.call(self, ...params)
        } else if (!timer) {
            // 否则两次触发的间隔时间没有超过等待时间，并且定时器还没有设置过，则等待remaining这么久才执行(浏览器执行本身也有时间间隔，大概4ms)
            // @ts-ignore
            timer = setTimeout(function () {
                clearTimeout(timer)
                timer = undefined
                previous = Date.now()
                func.call(self, ...params)
            }, remaining)
        }
    }
}